package com.pingan.pastry;

import com.pingan.pastry.validator.Node;
import com.pingan.pastry.validator.Rule;
import com.pingan.pastry.validator.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class VerifyInvoker implements Invoker {

    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
    private Rule rule;
    private Invoker invoker;

    public VerifyInvoker(Invoker invoker) {
        this.invoker = invoker;
    }

    @Override
    public Object invoke(Object request) throws InvocationTargetException, IllegalAccessException {
        List<Node> nodes = rule.getNodes();
        for (int i = 0; i < nodes.size(); i++) {
            Node node = nodes.get(i);
            String key = node.getKey();
            Object value = null;
            try {
                Method method = request.getClass().getMethod("get" + upperFirst(key));
                value = method.invoke(request);
            } catch (NoSuchMethodException e) {
                LOGGER.error("resolving request Method error,not such Method," + e);
            }
            List<Validator> validators = node.getValidators();
            if (validators != null && validators.size() > 0) {
                for (Validator validator : validators) {
                    validator.validate(value);
                }
            }
        }
        return invoker.invoke(request);
    }

    public String upperFirst(String value) {
        if (value != null) {
            String prefix = value.substring(0, 1).toUpperCase();
            value = prefix + value.substring(1, value.length());
        }
        return value;
    }

    @Override
    public Class<?> getRequestType() {
        return invoker.getRequestType();
    }

    @Override
    public Object getTarget() {
        return invoker.getTarget();
    }

    @Override
    public void setTarget(Object target) {
        invoker.setTarget(target);
    }

    public Rule getRule() {
        return rule;
    }

    public void setRule(Rule rule) {
        this.rule = rule;
    }
}
